const isEmpty = val => {
    if (typeof (val) === 'undefined' || (!val && typeof (val) !== 'undefined' && val !== 0)) {
        return true
    }
    return false
}

const resetRuleFn = () => ({
    validateStatus: undefined,
    help: undefined
})

const setRuleFn = (status, helpMsg) => ({
    validateStatus: status,
    help: helpMsg
})

const repeatCheckFn = (index = 0, key, value, list) => {
    if (!list.length) {
        return false
    }
    const checkList = list.slice(0, index)?.map(item => item[key]);

    return checkList.includes(value)
}

export default class ValidateFormTable {
    // 校验validateStatus类型取值，目前只支持error，可扩展
    statusMap = {
        success: '',
        error: 'error'
    }

    /**
     * rulesMap 自定义校验规则Map
     */
    constructor(rulesMap) {
        this.rulesMap = rulesMap
    }

    /**
     * form表单校验行初始化
     */
    initRulesFn() {
        const resMapRules = {}
        // eslint-disable-next-line no-restricted-syntax
        for (const key of Object.keys(this.rulesMap)) {
            resMapRules[key] = resetRuleFn()
        }
        return resMapRules
    }

    /**
     * 根据自定义的ruleMap进行校验，可以扩展
     * key 校验key
     * value 校验值
     * dataIndex 行数索引
     * data 数据来源  非必传，如果是要验证是否有重复项，则必须
     */
    ruleValidateMsg (key, value, dataIndex, data = []) {
        const itemRule = this.rulesMap[key] || []
        // eslint-disable-next-line no-plusplus
        for (let index = 0; index < itemRule.length; index++) {
            const element = itemRule[index];
            const { required, msg, min, repeat } = element
            if (required && isEmpty(value)) {
                return setRuleFn(this.statusMap.error, msg)
            }
            if (value < min) {
                return setRuleFn(this.statusMap.error, msg)
            }
            if (repeat && repeatCheckFn(dataIndex, key, value, data)) {
                return setRuleFn(this.statusMap.error, msg)
            }
        }
        return resetRuleFn()
    }

    /**
     * 总校验，用于按钮提交前的检查
     * data 需要校验的数据
     */
    validateMessageFn (data, callBackFn) {
        const validateDataList = data.slice()
        let resultBool = false
        // eslint-disable-next-line no-plusplus
        for (let index = 0; index < validateDataList.length; index++) {
            const element = validateDataList[index];
            // eslint-disable-next-line no-restricted-syntax
            for (const [key, value] of Object.entries(element)) {
                if (this.rulesMap[key]) {
                    const elementRule = this.ruleValidateMsg(key, value, index, data)
                    if (elementRule && elementRule.validateStatus) {
                        element.rules[key] = elementRule
                        resultBool = true
                    }
                }
            }
        }

        callBackFn(resultBool, validateDataList)
    }

    /**
     * 相同校验，用于重复项的实时监测
     * data 需要校验的数据
     */
    validateRepeatFn(data) {
        const repeatDataList = data.slice()
        // eslint-disable-next-line no-plusplus
        for (let index = 0; index < repeatDataList.length; index++) {
            const element = repeatDataList[index];
            // eslint-disable-next-line no-restricted-syntax
            for (const [key, value] of Object.entries(element)) {
                if (this.rulesMap[key] && element.rules[key].validateStatus) {
                    const elementRule = this.ruleValidateMsg(key, value, index, data)
                    element.rules[key] = elementRule
                }
            }
        }

        return repeatDataList
    }

    /**
     * 相同校验，用于重复项的实时监测
     * data 需要校验的数据
     */

    // eslint-disable-next-line class-methods-use-this
    validateFirstNumFn(data) {
        // eslint-disable-next-line no-plusplus
        for (let index = 0; index < data.length; ++index) {
            const element = data[index];
            // eslint-disable-next-line no-restricted-syntax
            for (const [, value] of Object.entries(element.rules)) {
                if (value.validateStatus === 'error') {
                    return index
                }
            }
        }
        return 0
    }
}
